package edu.kit.ksri.db.mturk.plugins.correctness.answers;

import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.JDOMParseException;
import org.jdom.input.SAXBuilder;

import com.amazonaws.mturk.requester.Assignment;

/**
 * Copyright (c) 2010-2011 Karlsruhe Institute of Technology (KIT), Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * 
 * --------------------------------------------------------------------------
 * 
 * Software: CSP/WMV tool for dynamic quality management of microtasks
 * http://www.ksri.kit.edu/Upload/Users/PeopleClouds/HCOMP2011_An_extendable_toolkit_for_managing_quality_of_human-based_eServices.pdf
 * 
 * Organization: Karlsruhe Institute of Technology (KIT), Germany
 * http://www.kit.edu
 * 
 * Project: PeopleClouds project of the Karlsruhe Service Research Institute(KSRI)
 * http://www.ksri.kit.edu/Default.aspx?PageId=818
 * 
 * Contributing authors: David Bermbach, Sandra Rath, Pascal Wichmann, Robert Kern
 * 
 * ---------------------------------------------------------------------------
 * 
 * note: subclasses may not have primitive parameters
 */
public abstract class AbstractAssignmentAnswer {

	/**
	 * the raw {@link String} value returned by {@link Assignment}.getAnswer().
	 * The XML structure is specified at<br>
	 * http://docs.amazonwebservices.com/AWSMechanicalTurkRequester
	 * /2008-04-01/ApiReference_QuestionFormAnswersDataStructureArticle.html
	 * 
	 * <br>
	 * <br>
	 * XSD:<br>
	 * http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2005-10-
	 * 01/QuestionFormAnswers.xsd
	 */
	protected final String rawAnswer;

	/**
	 * @param rawAnswer
	 */
	protected AbstractAssignmentAnswer(String rawAnswer) {
		super();
		this.rawAnswer = rawAnswer;
	}

	/**
	 * compares two {@link AssignmentAnswer} objects
	 * 
	 * @param other
	 * @return true if both objects contain the same content, false otherwise.
	 *         subclasses may define further details.
	 */
	public abstract boolean equals(AbstractAssignmentAnswer other);

	@Override
	public int hashCode() {
		return rawAnswer.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof AbstractAssignmentAnswer))
			return false;
		return this.equals((AbstractAssignmentAnswer) obj);
	}

	/**
	 * @return the rawAnswer
	 */
	public String getRawAnswer() {
		return this.rawAnswer;
	}
	
	/**
	 * creates key value pairs: key is always the content of a
	 * QuestionIdentifier element. value is the content of all other subelements
	 * of Answer elements concatenated. There are no guarantees regarding the
	 * order of the elements //FIXME: is the order of the returned results
	 * always the same for multiple choice answers?
	 * 
	 * @param rawAnswer
	 *            a {@link String} containing an XML message which can be
	 *            validated against http://mechanicalturk.amazonaws.com/
	 *            AWSMechanicalTurkDataSchemas
	 *            /2005-10-01/QuestionFormAnswers.xsd
	 * @return the created map of key-value pairs or null if an error occurred.
	 */
	public static HashMap<String, String> parseAnswer(String rawAnswer) {
		try {
			HashMap<String, String> res = new HashMap<String, String>();
			ByteArrayInputStream bais = new ByteArrayInputStream(rawAnswer
					.getBytes());
			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(bais);
			List<Element> answers = doc.getRootElement().getChildren();
			for (Element e : answers) {
				if (!e.getName().equals("Answer"))
					continue;
				List<Element> answerEntries = e.getChildren();
				String key = "", value = "";
				for (Element entry : answerEntries) {
					if (entry.getName().trim().equals("QuestionIdentifier"))
						key = entry.getValue().trim();
					else if (entry.getName().trim().equals("FreeText"))
						value = entry.getValue().trim();
					else if (entry.getName().trim().equals("UploadedFileKey"))
						value += "(UploadedFileKey=" + entry.getValue().trim()
								+ ")";
					else if (entry.getName().trim().equals(
							"UploadedFileSizeInBytes"))
						value += "(UploadedFileSizeInBytes="
								+ entry.getValue().trim() + ")";
					else if (entry.getName().trim().equals(
							"SelectionIdentifier"))
						value += "(SelectionIdentifier="
								+ entry.getValue().trim() + ")";
					else if (entry.getName().trim()
							.equals("OtherSelectionText"))
						value += "(OtherSelectionText="
								+ entry.getValue().trim() + ")";
					else
						throw new Exception("Found an unknown element: name="
								+ entry.getName().trim() + ", value="
								+ entry.getValue().trim());
				}
				res.put(key, value);
			}
			return res;
		}catch (JDOMParseException jpe){
			jpe.printStackTrace();
			System.out.println("!!!!Failure: " + rawAnswer);
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

}
